package msg

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
)

const (
	MagicNumber  = 0x12345678
	TypePing     = 1
	TypePong     = 2
	TypeRegister = 3
)

var msgTypeMap = map[byte]any{
	TypePing:     &Ping{},
	TypePong:     &Pong{},
	TypeRegister: &Register{},
}

type Msg interface {
	decode() (Msg, error)
	encode() []byte
}

type Ping struct {
	Timestamp int64
}

func (p Ping) decode() (Msg, error) {
	//TODO implement me
	panic("implement me")
}

func (p Ping) encode() []byte {
	//TODO implement me
	panic("implement me")
}

type Pong struct {
}

func (p Pong) decode() (Msg, error) {
	//TODO implement me
	panic("implement me")
}

func (p Pong) encode() []byte {
	//TODO implement me
	panic("implement me")
}

type Register struct {
	RemoteAddr string
	RemotePort int
}

func (r Register) decode() (Msg, error) {
	//TODO implement me
	panic("implement me")
}

func (r Register) encode() []byte {
	//TODO implement me
	panic("implement me")
}

func ReadMsg(conn net.Conn) (msg Msg, err error) {
	// 读取前四个字节
	magicBytes := make([]byte, 4)
	_, err = conn.Read(magicBytes)
	if err != nil {
		return nil, err
	}

	// 将字节转换为 uint32
	var magicValue uint32
	buf := bytes.NewBuffer(magicBytes)
	err = binary.Read(buf, binary.BigEndian, &magicValue)
	if err != nil {
		return nil, err
	}

	// 检查魔法数字是否匹配
	if magicValue != uint32(MagicNumber) {
		return nil, fmt.Errorf("invalid magic number: %d", magicValue)
	}

	// 读取版本号
	versionBytes := make([]byte, 1)
	_, err = conn.Read(versionBytes)
	if err != nil {
		return nil, err
	}

	var version uint8
	buf = bytes.NewBuffer(versionBytes)
	err = binary.Read(buf, binary.BigEndian, &version)
	if err != nil {
		return nil, err
	}

	// 读取消息类型
	typBytes := make([]byte, 1)
	_, err = conn.Read(typBytes)
	if err != nil {
		return nil, err
	}

	var typ uint8
	buf = bytes.NewBuffer(typBytes)
	err = binary.Read(buf, binary.BigEndian, &typ)
	if err != nil {
		return nil, err
	}

	switch typ {
	case 1:
		return &Ping{}, nil
	case 2:
		return &Pong{}, nil
	case 3:
		return &Register{}, nil
	}

	// 这里可以继续实现读取消息的逻辑
	// 目前返回 nil 和 nil 作为占位符
	return nil, nil
}
